import AttributeUtil from '@/AttributeUtil';
import BaseUtil from '@/BaseUtil';
import ForceUtil from '@/ForceUtil';
import PlayerUtil from '@/PlayerUtil';
import SelectUtil from '@/SelectUtil';
import SyncUtil from '@/SyncUtil';

declare global {
    interface UIBackPackItemModel {
        id: string;
        count: number;
        art: string;
        canStack: boolean;
        index: number;
        ubertip: string;
        price: number;
        name: string;
        attr: AppAttribute;
    }
}
export default class UIBackPackModel {
    /** 获取指定玩家的背包数据 */
    getBackPackData(p: player): UIBackPackItemModel[] {
        return this.DB[GetPlayerId(p)];
    }
    static reciseItem(p: player, { key, value }: { value: RecipeConfigModel; key: string }) {
        let _this = UIManager.UIBakpack.model;
        // 满足合成条件
        let attr = {};
        // 依次移除物品
        for (let id in value) {
            for (let i = 0; i < value[id]; i++) {
                let item = _this.getItemDataById(id, GetPlayerId(p));
                if (!item) break;
                AttributeUtil.add(attr, item.attr);
                // 如果count足够扣除，移除下一个物品
                let remain = item.count - value[id];
                if (remain > 0) {
                    item.count = remain;
                    break;
                } else {
                    _this.removeItemByIndex(item.index, p);
                }
            }
        }
        // 创建物品给英雄
        let u = SelectUtil.getAnHero(GetPlayerId(p));
        let item = CreateItem(key, GetUnitX(u), GetUnitY(u));
        AttributeUtil.setItemAttribute(item, attr);
        _this.addItem(item, p);
        se.emit('背包数据变化', { p });
    }
    /** 根据物品id获取指定物品的数据 */
    getItemDataById(id: string, pid: number) {
        let db = this.DB[pid];
        for (let i = 0; i < this.backPackSize; i++) {
            let item = db[i];
            if (item?.id == id) {
                return item;
            }
        }
        return null;
    }
    /** 取特定物品的数量 */
    getItemCount(id: string, pid: number) {
        let db = this.DB[pid];
        let c = 0;
        for (let i = 0; i < this.backPackSize; i++) {
            let item = db[i];
            if (item?.id == id) {
                c += item.count;
            }
        }
        return c;
    }
    /** 背包中使用物品 */
    private static useItem(p: player, d: UIBackPackItemModel) {
        let pid = GetPlayerId(p);
        let _this = UIManager.UIBakpack.model;
        let db = _this.DB[pid];
        if (d.count == 1) {
            _this.removeItemByIndex(d.index, p);
        } else {
            db[d.index].count--;
            se.emit('背包数据变化', { db, p });
        }
        se.emit('bag_item_used', { playerId: pid, id: d.id });
    }
    /** 根据索引清空背包格子数据 */
    removeItemByIndex(index: number, p: player) {
        let pid = GetPlayerId(p);
        let db = this.DB[pid];
        if (db != null) {
            if (db[index] != null) {
                // 同步事件给玩家添加物品
                db[index] = null;
                se.emit('背包数据变化', { db, p });
            }
        }
    }
    private _backPackSize = 30;
    get backPackSize() {
        return this._backPackSize;
    }
    DB: UIBackPackItemModel[][] = [];
    constructor() {
        let c = ForceUtil.getUserCount();
        for (let i = 0; i < c; i++) {
            this.DB[i] = [];
            for (let j = 0; j < this.backPackSize; j++) {
                this.DB[i][j] = null;
            }
        }

        SyncUtil.onSyncObjData('RM_true_item', UIBackPackModel.removeItem);
        SyncUtil.onSyncObjData('ADD_true_item', UIBackPackModel.addItemToPlayer);
        SyncUtil.onSyncObjData('BACKPACK_USE_ITEM', UIBackPackModel.useItem);
        SyncUtil.onSyncData('backpack_sort_item', UIBackPackModel.sortItem);
        SyncUtil.onSyncObjData('BACKPACK_RECISE_ITEM', UIBackPackModel.reciseItem);
    }
    static sortItem(p: player) {
        let pid = GetPlayerId(p);
        let _this = UIManager.UIBakpack.model;
        let db = _this.DB[pid];
        let arr: UIBackPackItemModel[] = [];
        for (let i = 0; i < _this.backPackSize; i++) {
            let item = db[i];
            arr.push(item);
        }
        for (let i = 0; i < arr.length; i++) {
            arr[i].index = i;
        }
        _this.DB[pid] = arr;
        se.emit('背包数据变化', { db, p: Player(pid) });
    }
    /** 同步数据，添加物品给玩家 */
    private static addItemToPlayer(p: player, d: UIBackPackItemModel) {
        let u = SelectUtil.getAnHero(GetPlayerId(p));
        let item = CreateItem(d.id, GetUnitX(u), GetUnitY(u));
        if (d.canStack) SetItemCharges(item, d.count);
        UnitAddItem(u, item);
        se.emit('属性刷新');
        // AttributeUtil.setItemAttribute(item, d.attr);
        Object.assign(AttributeUtil.getItemAttribute(item, true), d.attr);
        if (d.attr !== null) {
            for (let key in d.attr) {
                if (key.includes('_lv_up')) {
                    BaseUtil.runLater(0.1, () => {
                        se.emit(GameEvents.技能强化, { u });
                    });
                    break;
                }
            }
        }

        UIManager.UIBakpack.model.removeItemByIndex(d.index, p);
    }
    /** 同步删除进入背包的真实物品 */
    private static removeItem(p: player, { it, u }) {
        RemoveItem(it);
        se.emit('属性刷新');
        let h = SelectUtil.getAnHero(GetPlayerId(p));
        if (u == h) {
            BaseUtil.runLater(0.1, () => {
                se.emit(GameEvents.取消技能强化, { u });
            });
        }
    }
    /** 向背包中添加一件物品 */
    addItem(it: item, p: player, u?: unit) {
        let itemType = GetItemType(it);
        let canStack = itemType == ITEM_TYPE_CHARGED || GetItemCharges(it) > 1;
        let itemTypeId = id2string(GetItemTypeId(it));
        let playerIndex = GetPlayerId(p);
        let db = this.DB[playerIndex];
        if (canStack) {
            let index = this.findSameItemCanStack(itemTypeId, playerIndex);
            if (index != -1) {
                // 找到可堆叠并相同的物品格子，直接数量叠加即可
                db[index].count += GetItemCharges(it);
                SyncUtil.syncObjData('RM_true_item', { it, u });
                se.emit('背包数据变化', { db, p });
            } else {
                // 未找到可以叠加的格子，
                this.newItem(it, itemTypeId, canStack, playerIndex, u);
            }
        } else {
            this.newItem(it, itemTypeId, canStack, playerIndex, u);
        }
    }
    /** 处理添加新物品的逻辑 */
    private newItem(it: item, id: string, canStack: boolean, pid: number, u?: unit) {
        let index = this.findAnEmptyGrid(pid);
        if (index == -1) {
            PlayerUtil.message('背包已满');
            return;
        }
        let db = this.DB[pid];
        let count = canStack ? GetItemCharges(it) : 1;
        let itemId = GetItemTypeId(it);
        let itemDB = _g_objs.item[itemId];
        db[index] = {
            id,
            art: itemDB.Art,
            name: itemDB.Name,
            ubertip: itemDB.Description,
            price: S2I(itemDB.goldcost),
            count,
            canStack,
            index,
            attr: AttributeUtil.getItemAttribute(it),
        };
        if (it) {
            SyncUtil.syncObjData('RM_true_item', { it, u });
        }
        se.emit('背包数据变化', { db, p: Player(pid) });
    }
    /** 查找一个空的格子 */
    private findAnEmptyGrid(pid: number) {
        for (let i = 0; i < this.backPackSize; i++) {
            if (this.DB[pid][i] == null) {
                return i;
            }
        }
        return -1;
    }
    /** 查找一个相同并可以叠加的格子 */
    private findSameItemCanStack(itemTypeId: string, pid: number) {
        let db = this.DB[pid];
        for (let i = 0; i < this.backPackSize; i++) {
            if (!db[i]) continue;
            if (db[i].id == itemTypeId && db[i].canStack) {
                return i;
            }
        }
        return -1;
    }
    isInventoryFull(p: player) {
        return this.DB[GetPlayerId(p)].length >= this.backPackSize;
    }
}
